package vis.items.algo.sorting;

import java.util.Random;

import vis.app.controller.CodeController;
import vis.items.visualItem.AbstractSketch;

public class SelectionSortSketch extends AbstractSketch {
	private static final long serialVersionUID = -2487432826677392051L;

	private static final int FRAME_RATE = 2;

	private static final int SIZE = 12;
	private static final int MAX_VALUE = 100;
	private static final int SCALE_CONST = 4;
	private static final int BOTTOM_MARGIN = 150;
	private static final int LEFT_MARGIN = 100;

	private static final int BIN = 30;
	private static final int GAP = 10;
	private static final int TEXT_MARGIN = 5;
	private static final int TEXT_GAP = 20;

	private int[] data;
	private Random rnd;
	private int currentItem1 = 0;
	private int currentItem2 = 0;

	public SelectionSortSketch(String name) {
		super(name);
		data = new int[SIZE];
		randomData();
	}

	private void randomData() {
		rnd = new Random();
		for (int i = 0; i < SIZE; ++i) {
			data[i] = rnd.nextInt(MAX_VALUE);
		}
	}

	@Override
	public void init() {
		super.init();
		frameRate(FRAME_RATE);
	}

	@Override
	public void drawFrame() {
		CodeController.getInstance().startPushJobs();
		{
			updateLogicBubbleSort();
		}
		CodeController.getInstance().endPushJobs();

		drawArray();
	}

	private int ii = 0;
	private int jj = 0;

	private void updateLogicBubbleSort() {
		monitor("i", String.valueOf(ii));
		monitor("j", String.valueOf(jj));

		if (ii == SIZE - 1) {
			return;
		}

		currentItem1 = ii;
		currentItem2 = jj;

		monitor("data[i]", String.valueOf(data[ii]));
		monitor("data[j]", String.valueOf(data[jj]));

		if (data[jj] < data[ii]) {
			int temp = data[ii];
			data[ii] = data[jj];
			data[jj] = temp;
			highlight(new String[] { "26", "27", "28" });
		}

		jj++;
		highlight(new String[] { "24" });

		if (jj == SIZE) {
			ii++;
			highlight(new String[] { "23" });

			jj = ii;
		}

		while (CodeController.getInstance().hasHighlightJobs()) {
			CodeController.getInstance().executeOneHighlightJob();
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	// TODO REMOVE after testing
	private void bubbleSort() {
		for (int i = 0; i < SIZE - 1; ++i) {
			for (int j = i; j < SIZE; ++j) {
				if (data[j] < data[i]) {
					int temp = data[i];
					data[i] = data[j];
					data[j] = temp;
				}
			}
			dumpArray();
			drawArray();
		}
	}

	private void dumpArray() {
		String s = "";
		for (int i = 0; i < data.length; ++i) {
			s += String.valueOf(data[i]) + ",";
		}
		System.out.println(s + "\n");
	}

	private void drawArray() {
		background(0x12345);
		for (int i = 0; i < data.length; ++i) {
			if (currentItem1 == i) {
				fill(0, 255, 0);
			} else if (currentItem2 == i) {
				fill(255, 0, 0);
			} else {
				fill(255);
			}

			int itemHeight = data[i] * SCALE_CONST;
			int endY = this.height - BOTTOM_MARGIN;
			int startY = endY - itemHeight;
			int startX = LEFT_MARGIN + i * (BIN + GAP);
			rect(startX, startY, BIN, itemHeight);

			textSize(18);
			text(String.valueOf(data[i]), startX + TEXT_MARGIN, startY - TEXT_GAP);
			text(String.valueOf(i), startX + TEXT_MARGIN, startY + itemHeight + TEXT_GAP);

			noFill();
		}
	}

	private void monitor(String varName, String value) {
		CodeController.getInstance().addDebugVariable(varName, value);
	}

	private void highlight(String[] lines) {
		CodeController.getInstance().addHighlightJob(lines);
	}

	@Override
	public void updateLogicInterval() {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateDataInOneFrame() {
		// TODO Auto-generated method stub

	}
}
